using System;
using System.Collections.Generic;
using SCG.SolarVengeanceEngine;
using SCG.General;

namespace SCG.SolarVengeance.Scenarios
{
    public class ChaosCluster : Scenario
    {
        private ScenarioParameter paramStarSystems;
        private ScenarioParameter paramDensity;
        private ScenarioParameter enbBH;
        private ScenarioParameter enbPL;
        private ScenarioParameter enbWH;
        private ScenarioParameter ChaosChance;
        private List<StarSystem> vStar = new List<StarSystem>();
        private List<StarShip> vShip = new List<StarShip>();
        private List<Wormhole> vWormHole = new List<Wormhole>();
        private List<BlackHole> vBlackHole = new List<BlackHole>();
        private List<Pulsar> vPulsar = new List<Pulsar>();
        private Dictionary<SCGPoint,bool> vPoint = new Dictionary<SCGPoint, bool>();
        private double chancepercent = 0;
        private Random doublernd = new Random();

        public ChaosCluster()
        {
            paramStarSystems = CreateParameter("Number of Star Systems", 20, 2, 50);
            paramDensity = CreateParameter("Cluster Density", 2, 1, 10);
            enbBH = CreateParameter("Black Holes Enabled?", 1, 0, 1);
            enbPL = CreateParameter("Pulsars Enabled?", 1, 0, 1);
            enbWH = CreateParameter("Worm Holes Enabled?", 1, 0, 1);
            ChaosChance = CreateParameter("Chaos Chance 1 in #", 500, 200, 1000);
        }

        public override string Description
        {
            get
            {
                string dblnewline = "" + Convert.ToChar(13) + Convert.ToChar(10) + Convert.ToChar(13) + Convert.ToChar(10);
                return "This cluster is under the dominion of CHAOS! He will do everything in his power to destroy any order that exists in the Star Cluster." + 
                       " Star Lords entering CHAOS's domain will experience a complete change in the Star Cluster and all of the objects in the Star Cluster." +
                       " BEWARE! Using more starting resources in this cluster will increase this risk!" + dblnewline +
                       "This cluster setup is UGT's FarCapsClassic scenario.";
            }
        }
        public override string Author
        {
            get
            {
                return "Beat2k";
            }
        }
        public override void BuildScenario(int numPlayers, int capitalValues, int startingResources)
        {
            //clear previously assigned dictionaries
            vStar.Clear();
            vShip.Clear();
            vWormHole.Clear();
            vBlackHole.Clear();
            vPulsar.Clear();

            int startres = startingResources;
            if (startres < 100) startres = 100;
            chancepercent = ((double)startres / 100.0) / (double)ChaosChance.Value;
            SetValue("Chance", chancepercent.ToString(SVGame.CULTURE));

            //Create Capital Systems
            int Stars = numPlayers;
            StarSystem[] dcapital = new StarSystem[11];
            int Capitals = 0;
            int CapX = 0;
            int CapY = 0;
            int loops = 0;
            SCGPoint ptCapitals = new SCGPoint();
            bool CapitalsOK = false;

            while (Capitals < numPlayers)
            {
                do
                {
                    CapitalsOK = true;
                    loops++;
                    if (Capitals == 0)
                    {
                        ptCapitals = new SCGPoint(Random(20, 80), Random(20, 80));
                        double dist = Distance(ptCapitals.X, ptCapitals.Y, 50, 50);
                        CapitalsOK = dist < 30;
                    }
                    else
                    {
                        ptCapitals = new SCGPoint(Random(20, 80), Random(20, 80));
                        for (int d = 0; d < Capitals; d++)
                        {
                            CapX = dcapital[d].X;
                            CapY = dcapital[d].Y;
                            double dist = Distance(ptCapitals.X, ptCapitals.Y, CapX, CapY);
                            if (dist < 20)
                                CapitalsOK = false;
                        }
                    }
                }
                while (!CapitalsOK && loops < 1000000);
                dcapital[Capitals] = CreateStarSystem((int)ptCapitals.X, (int)ptCapitals.Y, 20, 10, 10, 20);
                AssignCapital(Game.Players[Capitals], new SCGRect(ptCapitals.X - 1, ptCapitals.Y - 1, 3, 3));
                Capitals++;
            }

            //Create StarCluster.
            CreateStarCluster(paramStarSystems.Value, 50, 50, 50, 50, 35, paramDensity.Value);

            //Create Random Nebula
            int numNebula = SVGame.RNG.Next(4) + 2;
            while (numNebula > 0)
            {
                CreateNebula(SVGame.RNG.Next(40) + 30, SVGame.RNG.Next(40) + 30, SVGame.RNG.Next(5) + 4, SVGame.RNG.Next(40) + 30);
                numNebula--;
            }
            //Create Random Wormholes
            int numWormholes = SVGame.RNG.Next(4) + 1;
            while (numWormholes > 0 && enbWH.Value == 1)
            {
                CreateWormhole(SVGame.RNG.Next(100), SVGame.RNG.Next(100), SVGame.RNG.Next(40) + 30, SVGame.RNG.Next(40) + 30);
                numWormholes--;
            }
            numWormholes = SVGame.RNG.Next(4) + 1;
            while (numWormholes > 0 && enbWH.Value == 1)
            {
                CreateWormhole(SVGame.RNG.Next(40) + 30, SVGame.RNG.Next(40) + 30, SVGame.RNG.Next(100), SVGame.RNG.Next(100));
                numWormholes--;
            }
            //Create Random Pulsars within the cluster
            int pulsars = Random(numPlayers, (numPlayers + 3));
            while (pulsars > 0 && enbPL.Value == 1)
            {
                SCGPoint ptPulsar = new SCGPoint();
                ptPulsar = new SCGPoint(Random(25, 75), Random(25, 75));
                CreatePulsar((int)ptPulsar.X, (int)ptPulsar.Y);
                pulsars--;
            }

            //Create Black Holes just outside the cluster perimeter
            int BlackHolesCreated = 0;
            Dictionary<int, int> BHInfoXpos = new Dictionary<int, int>();
            Dictionary<int, int> BHInfoYpos = new Dictionary<int, int>();
            int bhX = 0;
            int bhY = 0;
            int BlackHoles = Random(numPlayers, (numPlayers + 10));
            while (BlackHoles > 0 && enbBH.Value == 1)
            {
                bool BlackHolesOK = false;
                SCGPoint ptBlackHoles = new SCGPoint();
                do
                {
                    ptBlackHoles = new SCGPoint(Random(10, 90), Random(10, 90));
                    double dist = Distance(ptBlackHoles.X, ptBlackHoles.Y, 50, 50);
                    BlackHolesOK = dist > 40;
                    if (BlackHolesOK == true)
                    {
                        if (BlackHolesCreated > 0)
                        {
                            for (int d = 0; d < BlackHolesCreated; d++)
                            {
                                bhX = BHInfoXpos[d];
                                bhY = BHInfoYpos[d];
                                double bhdist = Distance(ptBlackHoles.X, ptBlackHoles.Y, bhX, bhY);
                                if (bhdist < 10)
                                    BlackHolesOK = false;
                            }
                        }
                    }
                }
                while (!BlackHolesOK);
                CreateBlackHole((int)ptBlackHoles.X, (int)ptBlackHoles.Y, Random(10, 15));
                BHInfoXpos.Add(BlackHolesCreated, (int)ptBlackHoles.X);
                BHInfoYpos.Add(BlackHolesCreated, (int)ptBlackHoles.Y);
                BlackHolesCreated++;
                BlackHoles--;
            }

            StarSystem tmps = null;
            for (int d = 0; d < Game.StarSystems.Count; d++)
            {
                tmps = Game.StarSystems[d];
                vStar.Add(tmps);
            }

            Pulsar tmpp = null;
            for (int d = 0; d < Game.Pulsars.Count; d++)
            {
                tmpp = Game.Pulsars[d];
                vPulsar.Add(tmpp);
            }

            Wormhole tmpw = null;
            for (int d = 0; d < Game.Wormholes.Count; d++)
            {
                tmpw = Game.Wormholes[d];
                vWormHole.Add(tmpw);
            }

            BlackHole tmpb = null;
            for (int d = 0; d < Game.BlackHoles.Count; d++)
            {
                tmpb = Game.BlackHoles[d];
                vBlackHole.Add(tmpb);
            }
        }

        //this communicates the chancepct to clients
        public override void ClientInitialize()
        {
            string chance = GetValue("Chance");
            try
            {
                chancepercent = Double.Parse(chance, SVGame.CULTURE);
            }
            catch
            {
            }
        }

        //Dynamic processing
        public override void ProcessImpulse(int impulse)        
        {
            StarShip tmps = null;
            vShip.Clear();
            for (int d = 0; d < Game.StarShips.Count; d++)
            {
                tmps = Game.StarShips[d];
                vShip.Add(tmps);
            }

            if (doublernd.NextDouble() <= chancepercent)
            {
                SCGPoint ptm = new SCGPoint();
                int rnd = Random(0, 7);
                if (rnd == 0) DynamicEvents.DisplayMessage("The whole cluster has been reshaped in an instant!");
                if (rnd == 1) DynamicEvents.DisplayMessage("OH NO! CHAOS has struck again!");
                if (rnd == 2) DynamicEvents.DisplayMessage("Catastrophic changes in events have taken place!");
                if (rnd == 3) DynamicEvents.DisplayMessage("What in the universe has just happened?!?!?!");
                if (rnd == 4) DynamicEvents.DisplayMessage("The space-time fabric has just been turned inside out!");
                if (rnd == 5) DynamicEvents.DisplayMessage("The laws of physics has been broken again!");
                if (rnd == 6) DynamicEvents.DisplayMessage("What kind of phonomena is causing all of this CHAOS!?!?!?");
                if (rnd == 7) DynamicEvents.DisplayMessage("I think this is the end of the universe!!!!!!");
                //The randomization begins!
                for (int d = 0; d < 100; d++)
                {
                    DynamicEvents.CreateExplosion(Random(10, 89), Random(10, 89), 50, SCGColor.Red, SCGColor.Yellow, 1, 8, 200, true);
                }

                StarSystem tmpss = null;
                for (int d = 0; d < Game.StarSystems.Count; d++)
                {
                    tmpss = Game.StarSystems[d];
                    ptm.X = Random(1,98);
                    ptm.Y = Random(1,98);
                    while (vPoint.ContainsKey(ptm))
                    {
                        ptm.X = Random(1,98);
                        ptm.Y = Random(1,98);
                    }
                    DynamicEvents.RelocateObject(tmpss, (int)ptm.X, (int)ptm.Y);
                    vPoint.Add(ptm, true);
                }

                Wormhole tmpw = null;
                for (int d = 0; d < Game.Wormholes.Count; d++)
                {
                    tmpw = Game.Wormholes[d];
                    ptm.X = Random(1, 98);
                    ptm.Y = Random(1, 98);
                    while (vPoint.ContainsKey(ptm))
                    {
                        ptm.X = Random(1, 98);
                        ptm.Y = Random(1, 98);
                    }
                    DynamicEvents.RelocateObject(tmpw, (int)ptm.X, (int)ptm.Y);
                    vPoint.Add(ptm, true);
                }

                BlackHole tmpb = null;
                for (int d = 0; d < Game.BlackHoles.Count; d++)
                {
                    tmpb = Game.BlackHoles[d];
                    ptm.X = Random(1, 98);
                    ptm.Y = Random(1, 98);
                    while (vPoint.ContainsKey(ptm))
                    {
                        ptm.X = Random(1, 98);
                        ptm.Y = Random(1, 98);
                    }
                    DynamicEvents.RelocateObject(tmpb, (int)ptm.X, (int)ptm.Y);
                    vPoint.Add(ptm, true);
                }

                Pulsar tmpp = null;
                for (int d = 0; d < Game.Pulsars.Count; d++)
                {
                    tmpp = Game.Pulsars[d];
                    ptm.X = Random(1, 98);
                    ptm.Y = Random(1, 98);
                    while (vPoint.ContainsKey(ptm))
                    {
                        ptm.X = Random(1, 98);
                        ptm.Y = Random(1, 98);
                    }
                    DynamicEvents.RelocateObject(tmpp, (int)ptm.X, (int)ptm.Y);
                    vPoint.Add(ptm, true);
                }

                tmps = null;
                for (int d = 0; d < Game.StarShips.Count; d++)
                {
                    tmps = Game.StarShips[d];
                    ptm.X = Random(0, 99);
                    ptm.Y = Random(0, 99);
                    while (vPoint.ContainsKey(ptm))
                    {
                        ptm.X = Random(0, 99);
                        ptm.Y = Random(0, 99);
                    }
                    DynamicEvents.RelocateObject(tmps, (int)ptm.X, (int)ptm.Y);
                    vPoint.Add(ptm, true);
                }
                vPoint.Clear();
            }         
        }
    }
}
